home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / lib / c / aceports.c next >
Encoding:
C/C++ Source or Header  |  1998-10-04  |  7.3 KB  |  398 lines

  1. /* 
  2. ** ACE messaging mechanism. Uses Exec Message Ports.
  3. ** Copyright (C) 1998 David Benn
  4. ** 
  5. ** This program is free software; you can redistribute it and/or
  6. ** modify it under the terms of the GNU General Public License
  7. ** as published by the Free Software Foundation; either version 2
  8. ** of the License, or (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. ** 
  19. ** Up to 255 message ports per program are allowed for.
  20. ** In reality the number of task signals will limit this
  21. ** to a lesser value.
  22. **
  23. ** All of the following "MessageXXXX" functions set "error_code"
  24. ** which is accessible via the BASIC ERR function.
  25. **
  26. ** MessageOpen()     -  Sets up a message channel.
  27. ** MessageClose()    -  Cleans up a message channel.
  28. ** MessageWrite()    -  Writes a message to a channel.
  29. ** MessageRead()    -  Reads a message from a channel.
  30. ** MessageWait()    -  Waits for a message on a channel.
  31. ** MessageClear()    -  Clears a message channel.
  32. **
  33. ** Author: David J Benn
  34. **   Date: 23rd,24th,26th,27th January 1994,
  35. **       13th,15th February 1994,
  36. **       22nd,23rd,28th August 1994,
  37. **       10th,11th September 1994
  38. */
  39.  
  40. #include <exec/types.h>
  41. #include <exec/ports.h>
  42. #include <exec/memory.h>
  43.  
  44. #define MINCHANNEL             1
  45. #define MAXCHANNEL         255
  46.  
  47. #define NO_ERR              0
  48. #define OPEN_ERR           400
  49. #define CLOSE_ERR           401
  50. #define READ_ERR           402
  51. #define WRITE_ERR           403
  52. #define WAIT_ERR        404
  53. #define CHAN_ERR        405
  54.  
  55. #define CLEARED_PUBLIC_MEM      5L
  56. #define CLEARED_ANY_MEM      7L
  57.  
  58. /* structure types */
  59. typedef struct ACEport
  60. {
  61.     char    mode;        /* read or write */
  62.     char     *name;         /* name of target port */
  63.     struct     MsgPort *port;    /* message or reply port */
  64. } ACEPORT;
  65.  
  66. typedef struct ACEmsg
  67. {
  68.     struct     Message header;
  69.     char    *msg;    
  70. } ACEMSG;
  71.  
  72. /* globals */
  73. BOOL    first=TRUE;
  74. ACEPORT    aceport[MAXCHANNEL+1];
  75.  
  76. /* externals */
  77. extern    ULONG    error_code;
  78.  
  79. /* external functions */
  80. extern    void     *alloc();
  81. extern    char     *stringcopy();
  82. extern    ULONG     stringlength();
  83. extern    struct     MsgPort *CreatePort();
  84. extern    struct     MsgPort *FindPort();
  85. extern    void    DeletePort();
  86. extern    void    PutMsg();
  87. extern    ACEMSG    *GetMsg();
  88. extern    void    WaitPort();
  89.  
  90. /* functions */
  91. BOOL bad(channel)
  92. SHORT     channel;
  93. {
  94. /* 
  95. ** Return TRUE if channel number is invalid.
  96. */
  97.  
  98.     if (channel < MINCHANNEL || channel > MAXCHANNEL) 
  99.         return(TRUE);
  100.     else
  101.             return(FALSE);
  102. }
  103.  
  104. void MessageOpen(mode,name,channel)
  105. char      *mode,*name;
  106. SHORT     channel;
  107. {
  108. SHORT      i;
  109. /* 
  110. ** Set up a message channel.
  111. */
  112.  
  113.     /* clear port info' array? */
  114.     if (first)
  115.     {
  116.         first=FALSE;
  117.         for (i=1;i<=255;i++)
  118.         {
  119.             aceport[i].mode = ' ';
  120.             aceport[i].name = NULL;
  121.             aceport[i].port = NULL;
  122.         }
  123.     }
  124.  
  125.     /* 
  126.     ** Can we use this channel and port-name? 
  127.     */
  128.     if (bad(channel)) 
  129.         { error_code = CHAN_ERR; return; }
  130.     else
  131.     if (aceport[channel].port != NULL) 
  132.         { error_code = OPEN_ERR; return; }
  133.     else
  134.     {
  135.       switch(*mode)
  136.       {
  137.         case 'r' :
  138.         case 'R' :     if (FindPort(name)) 
  139.                    { error_code = OPEN_ERR; return; }
  140.                 aceport[channel].mode = 'R';
  141.                 break;
  142.  
  143.         case 'w' :
  144.         case 'W' :    if (!FindPort(name)) 
  145.                    { error_code = OPEN_ERR; return; }
  146.                 aceport[channel].mode = 'W';
  147.                 break;
  148.  
  149.         default  :    aceport[channel].mode = ' ';
  150.                 error_code = OPEN_ERR; return;
  151.                 break;
  152.       }
  153.  
  154.       /* 
  155.       ** Create a named message port. 
  156.       */    
  157.       if (aceport[channel].mode == 'R')
  158.       {
  159.         if (!(aceport[channel].port = CreatePort(name,0L)))
  160.         {
  161.             error_code = OPEN_ERR;
  162.             return;
  163.         }
  164.       }
  165.       else
  166.       /* 
  167.       ** Create an unnamed (reply) message port 
  168.       ** and store target port name.
  169.       */
  170.       if (aceport[channel].mode == 'W')
  171.       {
  172.         if (!(aceport[channel].port = CreatePort(NULL,0L)))
  173.         {
  174.             error_code = OPEN_ERR;
  175.             return;            
  176.         }
  177.         else
  178.         {
  179.             aceport[channel].name = (char *)
  180.                 alloc(CLEARED_ANY_MEM,stringlength(name)+1);
  181.  
  182.             if (aceport[channel].name == NULL) 
  183.             {
  184.                 error_code = OPEN_ERR;
  185.                 return;
  186.             }        
  187.             else
  188.                 stringcopy(aceport[channel].name,name);
  189.         }
  190.       }
  191.        else
  192.         /* Read or Write mode not specified! */
  193.         error_code = OPEN_ERR;
  194.     }
  195. }
  196.  
  197. void MessageClose(channel)
  198. SHORT     channel;
  199. {
  200. /*
  201. ** Remove a message channel.
  202. */
  203.  
  204.     if (bad(channel)) 
  205.     {
  206.         error_code = CHAN_ERR;
  207.            return;
  208.     }
  209.     else
  210.     if (aceport[channel].port == NULL) 
  211.     {
  212.         error_code = CLOSE_ERR;
  213.         return;
  214.     }
  215.     else
  216.     {
  217.         DeletePort(aceport[channel].port);
  218.         aceport[channel].mode = ' ';
  219.         aceport[channel].name = NULL;
  220.         aceport[channel].port = NULL;
  221.     }
  222. }
  223.  
  224. void MessageWrite(msg_string,channel)
  225. char    *msg_string;    
  226. SHORT    channel;
  227. {
  228. static     ACEMSG     pkt;
  229. struct    MsgPort    *port;
  230. /* 
  231. ** Write a message to a channel. 
  232. ** ReplyPort is aceport[channel].port.
  233. */
  234.     if (bad(channel))
  235.     {
  236.         error_code = CHAN_ERR;    
  237.         return;
  238.     }
  239.     else
  240.     if (aceport[channel].port == NULL) 
  241.     {
  242.         error_code = WRITE_ERR;
  243.         return;
  244.     }
  245.     else
  246.     if (aceport[channel].mode != 'W')
  247.     {
  248.         error_code = WRITE_ERR;
  249.         return;
  250.     }
  251.        else
  252.     if (msg_string[0] == '\0')
  253.     {
  254.         error_code = WRITE_ERR;
  255.         return;
  256.     }
  257.     else
  258.     {
  259.         /*
  260.         ** Message header: type, size, replyport.
  261.         */
  262.         pkt.header.mn_Node.ln_Type = NT_MESSAGE;
  263.         pkt.header.mn_ReplyPort = aceport[channel].port;
  264.         pkt.header.mn_Length = sizeof(ACEMSG);
  265.  
  266.         /*
  267.         ** Message body.
  268.         */
  269.         pkt.msg = (char *)
  270.               alloc(CLEARED_PUBLIC_MEM,stringlength(msg_string)+1);
  271.         if (pkt.msg == NULL) 
  272.         {
  273.             error_code = WRITE_ERR;
  274.             return;
  275.         }
  276.         else
  277.             stringcopy(pkt.msg,msg_string);
  278.             
  279.         /* 
  280.         ** Make sure target port still exists before
  281.         ** writing to it! 
  282.         */
  283.         if (port = FindPort(aceport[channel].name))
  284.         {
  285.             PutMsg(port,&pkt);
  286.         }
  287.         else
  288.             error_code = WRITE_ERR;
  289.     }
  290. }
  291.  
  292. void MessageRead(msg_string,channel)
  293. char    *msg_string;
  294. SHORT     channel;
  295. {
  296. ACEMSG    *pkt;
  297. /*
  298. ** Read a message from a channel.
  299. */
  300.  
  301.     /* assume NULL string should be returned */
  302.     msg_string[0] = '\0';
  303.  
  304.     if (bad(channel)) 
  305.     {
  306.         error_code = CHAN_ERR;
  307.         return;
  308.     }
  309.     else
  310.     if (aceport[channel].port == NULL) 
  311.     {
  312.         error_code = READ_ERR;
  313.         return;
  314.     }
  315.     else
  316.     if (aceport[channel].mode != 'R')
  317.     {
  318.         error_code = READ_ERR;
  319.         return;
  320.     }
  321.     else
  322.     {
  323.       pkt = GetMsg(aceport[channel].port);
  324.       if (pkt != NULL) 
  325.       {
  326.         stringcopy(msg_string,pkt->msg);
  327.         ReplyMsg(pkt);
  328.         /* 
  329.         ** Polling sets error_code to READ_ERR 
  330.         ** so clear it if necessary. We don't
  331.         ** really want to clear just _any_ error
  332.         ** (eg. OPEN_ERR).
  333.         */
  334.         if (error_code == READ_ERR) error_code = NO_ERR; 
  335.       }    
  336.       else
  337.         error_code = READ_ERR;
  338.     }
  339. }
  340.     
  341. void MessageWait(channel)
  342. SHORT channel;
  343. {
  344. ACEMSG *pkt;
  345. /* 
  346. ** Wait for a message on a channel.
  347. */
  348.  
  349.     if (bad(channel))
  350.     {
  351.         error_code = CHAN_ERR;
  352.         return;
  353.     }
  354.     else
  355.     if (aceport[channel].port == NULL) 
  356.     {
  357.         error_code = WAIT_ERR;
  358.         return;
  359.     }
  360.     else
  361.     {
  362.         /* await a message */
  363.         WaitPort(aceport[channel].port);
  364.     }
  365. }
  366.  
  367. void MessageClear(channel)
  368. SHORT channel;
  369. {
  370. ACEMSG *pkt;
  371. /* 
  372. ** Clear a message channel (prior to reading it).
  373. */
  374.  
  375.     if (bad(channel))
  376.     {
  377.         error_code = CHAN_ERR;
  378.         return;
  379.     }
  380.     else
  381.     if (aceport[channel].port == NULL) 
  382.     {
  383.         error_code = READ_ERR;
  384.         return;
  385.     }
  386.     else
  387.     if (aceport[channel].mode != 'R')
  388.     {
  389.         error_code = READ_ERR;
  390.         return;
  391.     }
  392.     else
  393.     {
  394.         /* clear the port */
  395.         while (pkt = GetMsg(aceport[channel].port)) ReplyMsg(pkt);
  396.     }
  397. }
  398.